<?php

namespace App\Kuafu\CustomerCoupon\Model;

use App\Kuafu\Activity\Model\ActivityModel;
use App\Kuafu\Base\Model\BaseModel;
use App\Kuafu\Base\Model\Traits\KfSoftDeletes;
use App\Kuafu\Base\Model\Traits\KfSplitRelation;
use App\Kuafu\Coupon\Model\CouponModel;
use App\Kuafu\Customer\Model\CustomerModel;
use App\Kuafu\CustomerCoupon\Convert\CustomerCouponConvent;
use App\Kuafu\CustomerCoupon\Enum\CodeEnum;
use App\Kuafu\CustomerCoupon\Enum\CustomerCouponCacheEnum;
use App\Kuafu\CustomerCoupon\Service\CustomerEnableCouponService;
use App\Kuafu\Order\Model\OrderCouponModel;
use App\Kuafu\Order\Model\OrderCouponSplitModel;
use App\Kuafu\Order\Model\OrderModel;
use App\Kuafu\Order\Model\OrderSplitModel;
use App\Kuafu\Product\Model\Product;
use App\Kuafu\Shop\Model\Shop;
use App\Kuafu\Shop\Service\ShopService;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;

class CustomerCouponModel extends BaseModel
{
    use KfSoftDeletes, KfSplitRelation;

    protected $connection = 'mysql';
    protected $table      = 'customer_coupons';
    protected $primaryKey = 'id';
    protected $fillable   = ["sourceName"]; //可更新字段，用来过滤create/save方法的参数
    protected $appends    = ['endAtDate', 'startAtDate'];


    const USE_TYPE_MERCHANT = 1;

    const SOURCE_ACTIVITY       = 1;//活动
    const SOURCE_COUPON_PACKAGE = 2;//券包

    protected $hidden = [
        'updatedAt',
        'isDeleted'
    ];

    public function couponShopRel()
    {
        return $this->hasMany(CustomerCouponShopMappingModel::class, 'customerCouponId', 'id');
    }

    public function couponRel()
    {
        return $this->hasOne(CouponModel::class, 'id', 'couponId');
    }

    /**
     * 下单获取用户优惠券
     *
     * @param int $userId
     * @param int $shopId
     * @return array|Builder[]|Collection
     */
    public static function userCoupons(int $userId, int $shopId = 0)
    {
        return self::query()
                   ->with([
                       'couponShopRel' => function ($query) {
                           return $query->select(['customerCouponId', 'shopId']);
                       }
                   ])
                   ->when($shopId > 0, function ($query) use ($shopId) {
                       $query->with("productRel", function ($query) use ($shopId) {
                           $query->where("menuId", ShopService::getShopInfo($shopId)->menuId)
                                 ->select(["id", "menuId", "imageUrl"]);
                       });
                   })
                   ->where('endAt', ">=", time())
                   ->where("userId", $userId)
                   ->where("status", 0)
                   ->get()->map(function (CustomerCouponModel $customerCouponModel) {
                if (
                    $customerCouponModel->couponType == CodeEnum::COUPON_TYPE_EXCHANGE
                    &&
                    $customerCouponModel->productRel
                ) {
                    $customerCouponModel->productRel->imageUrl = picturePath($customerCouponModel->productRel->imageUrl);
                }
                return $customerCouponModel;
            })->values();
    }

    /**
     * 用户当前优惠券优惠券
     */
    public static function getUserCouponList($userId, int $couponType = 0, int $availableSource = 0, int $shopId = 0, int $isGetNowCoupon = 0)
    {
        $time = time();
        return self::query()
                    ->with(["couponShopRel"])
                    ->when($shopId > 0,function($query)use($shopId){
                        $shopModel = Shop::query()->where("id", $shopId)->first();
                        $query->where(function($query)use($shopId, $shopModel){
                            $query->where(function($query)use($shopId){
                                $query->whereHas("couponShopRel", function($query)use($shopId) {
                                    $query->where("shopId", $shopId);
                                })->where("shopType", CodeEnum::COUPON_SHOP_TYPE_PART);
                            })->orWhere("shopType",$shopModel->type)->orWhere("shopType", CodeEnum::COUPON_SHOP_TYPE_ALl);
                        });
                    })
                   ->with([
                        'couponRel' => function ($query) {
                            return $query->select(['id', 'name','availableSource']);
                        }
                   ])
                    ->when($couponType, function ($query) use ($couponType) {
                        $query->where('couponType' , $couponType);
                    })
                    ->when($availableSource, function ($query) use ($availableSource) {
                        $availableSourceList = CustomerCouponConvent::getAvailableSourceIds($availableSource);
                        $query->whereIn('availableSource' , $availableSourceList);
                    })
                    ->when($isGetNowCoupon, function ($query) use ($time) {
                        // 仅获取在有效期的优惠券
                        $query->where('startAt', "<=", $time);
                    })
                   ->where('endAt', ">=", $time)
                   ->where(['userId' => $userId, 'status' => 0])
                   ->get();

    }

    /**
     * 获取用户历史优惠券 已使用和已过期和已锁定
     * @param $userId
     */
    public static function getUserHistoryCouponList($userId, $pageNum, $pageSize, int $couponType, int $availableSource, int $shopId)
    {
        $time = time();
        return self::query()
                    ->with([
                        'couponShopRel' => function ($query)use ($shopId) {
                            return $query->select(['customerCouponId', 'shopId'])
                                         ->when($shopId, function ($query) use ($shopId) {
                                             $query->where('shopId', $shopId);
                                         });
                        }
                    ])
                    ->with([
                        'couponRel' => function ($query) {
                            return $query->select(['id', 'name','availableSource']);
                        }
                    ])
                    ->when($couponType, function ($query) use ($couponType) {
                        $query->where('couponType' , $couponType);
                    })
                    ->when($availableSource, function ($query) use ($availableSource) {
                        $availableSourceList = CustomerCouponConvent::getAvailableSourceIds($availableSource);
                        $query->whereIn('availableSource' , $availableSourceList);
                    })
                   ->where('userId', $userId)
                   ->where(function ($query) use ($time) {
                       $query->where('endAt', "<=", $time)
                             ->orWhereIn('status', [CodeEnum::COUPON_STATUS_USED, CodeEnum::COUPON_STATUS_LOCK]);
                   })
                   ->orderBy('endAt', 'DESC')
                   ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

    }

    public static function getCouponListByCodeList($userId, $couponCodeList, int $shopId = 0)
    {
        return self::query()
                   ->with([
                       'couponShopRel' => function ($query) {
                           return $query->select(['customerCouponId', 'shopId']);
                       }
                   ])
                   ->when($shopId > 0, function ($query) use ($shopId) {
                       $query->with("productRel", function ($query) use ($shopId) {
                           $query->where("menuId", ShopService::getShopInfo($shopId)->menuId)
                                 ->select(["id", "menuId", "imageUrl"]);
                       });
                   })
                   ->where('userId', '=', $userId)
                   ->whereIn('couponCode', $couponCodeList)
                   ->get();
    }

    public static function insertData(array $data)
    {
        return self::query()->insertGetId($data);
    }

    public static function setStatus(int $id, int $status): int
    {
        return self::query()->where('id', $id)->update(['status' => $status]);
    }

    /**
     * 锁定用户 优惠券
     * @param array $ids
     * @return int
     */
    public static function lockCustomerCoupon(array $ids = []): bool
    {
        if (empty($ids)) {
            return false;
        }

        // 清除核销券缓存
        foreach ($ids as $customerCouponId) {
            Cache::forget(CustomerCouponCacheEnum::getUserCouponStatusKey($customerCouponId));
        }

        self::query()->whereIn('id', $ids)->update(['status' => CodeEnum::COUPON_STATUS_LOCK]);

        return true;
    }

    /**
     * 核销优惠券 时间差
     * @param array $ids
     * @return int
     */
    public static function verificationCoupon($ids = []): int
    {
//        return self::query()->whereIn('id', $ids)->update(['status' => CodeEnum::COUPON_STATUS_USED]);
    }

    public function getStartAtDateAttribute()
    {
        if ($this->useTimeType == CodeEnum::USE_TIME_TYPE_FIXED) {
            return date('Y-m-d', $this->startAt);
        } else {
            $timeDifference = (int)floor(($this->startAt - time()) / CodeEnum::COUPON_DAY_TIME);

            $endTimeDifference = $this->endAt - time();
            if ($endTimeDifference < CodeEnum::COUPON_DAY_DIFFERENCE) {
                return "已失效";
            }
            if ($timeDifference == CodeEnum::COUPON_DAY_TOMORROW) {
                if (date('Y-m-d', $this->startAt) === date('Y-m-d', strtotime('+1 day'))) {
                    return "明天生效";
                } else {
                    return CodeEnum::COUPON_DAY_TOMORROW . '天后生效';
                }
            } elseif ($timeDifference == CodeEnum::COUPON_DAY_DIFFERENCE) {
                if (date('Y-m-d', $this->startAt) === date('Y-m-d', time())) {
                    return "当天生效";
                } else {
                    return '明天生效';
                }
            } elseif ($timeDifference > CodeEnum::COUPON_DAY_DIFFERENCE) {
                return $timeDifference . "天后生效";
            } else {
                return "已生效";
            }
        }
    }

    public function getEndAtDateAttribute()
    {
        if ($this->useTimeType == CodeEnum::USE_TIME_TYPE_FIXED) {
            return date('Y-m-d', $this->endAt);
        } else {
            $timeDifference = floor(($this->endAt - time()) / CodeEnum::COUPON_DAY_TIME);
            if ($timeDifference == CodeEnum::COUPON_DAY_TOMORROW) {
                if (date('Y-m-d', $this->endAt) === date('Y-m-d', strtotime('+1 day'))) {
                    return "明天失效";
                } else {
                    return CodeEnum::COUPON_DAY_TOMORROW . '天后失效';
                }
            }
            if ($timeDifference < CodeEnum::COUPON_DAY_DIFFERENCE) {
                return "已失效";
            } elseif ($timeDifference == CodeEnum::COUPON_DAY_DIFFERENCE) {
                if (date('Y-m-d', $this->endAt) === date('Y-m-d', time())) {
                    return "当天失效";
                } else {
                    return '明天失效';
                }
            } else {
                return date('Y-m-d', $this->endAt);
            }
        }
    }

    //与用户关联
    public function customers()
    {
        return $this->belongsTo(CustomerModel::class, 'userId', 'id');
    }


    //用户优惠券表与订单表关联
    public function orderRel()
    {
        return $this->hasManyThrough(
            OrderModel::class,
            OrderCouponModel::class,
            'customerCouponId',
            'orderId',
            'id',
            'orderId'
        );
    }

    //用户优惠券表与店铺表关联
    public function shopRel()
    {
        return $this->belongsTo(
            OrderCouponModel::class,
            'id',
            'customerCouponId',
        );
    }

    /**
     * @return HasOne
     */
    public function activityRel(): HasOne
    {
        return $this->hasOne(ActivityModel::class, "id", "activityId");
    }

    /**
     * @param string $couponCode
     * @return Builder|Model|object|null
     */
    public static function getCustomerCouponDetailByCouponCode(string $couponCode)
    {
        return self::query()->where("couponCode", $couponCode)->first();
    }

    /**
     * 获取可用产品
     *
     * @return HasOne
     */
    public function productRel(): HasOne
    {
        return $this->hasOne(Product::class, "id", "canUseProduct");
    }
}
